package com.java.base.exercise.jvm;

import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;

import java.lang.reflect.Method;

/**
 * @Author RenPu
 * @Date 2021/11/17 15:20
 * @Version 1.0
 * @Description: 模拟元空间区域OOM, 使用CGLIB动态代理，动态创建好多类让Metaspace区内存OOM
 * -XX:MetaspaceSize=10m  元空间区初始值：10M
 * -XX:MaxMetaspaceSize=10m  元空间最大值: 10M
 *
 *
 * -XX:+UseParNewGC
 * -XX:+UseConcMarkSweepGC
 * -XX:MetaspaceSize=10m
 * -XX:MaxMetaspaceSize=10m
 * -XX:+PrintGCDetails
 * -Xloggc:gc.log
 * -XX:+HeapDumpOnOutOfMemoryError
 * -XX:HeapDumpPath=./
 **/
public class MetaspaceOOM {

    //private static volatile Enhancer enhancer=null;
    public static void main(String[] args) {
        long count=0;
        //if(enhancer==null){  这样加上判断可以避免频繁创建类，加载到元空间区导致OOM
        while (true) {
            System.out.println("目前创建了"+(++count)+"个Car类的子类对象......");
            Enhancer enhancer = new Enhancer();
            enhancer.setSuperclass(Car.class);
            enhancer.setUseCache(false);
            enhancer.setCallback(new MethodInterceptor() {
                @Override
                public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
                    if(method.getName().equals("carRun")){

                        System.out.println("汽车启动前，进行安全检查.........");
                        return   proxy.invokeSuper(obj,args);
                    }else {
                        return proxy.invokeSuper(obj,args);
                    }

                }
            });
        //}
            Car car= (Car) enhancer.create();
            car.carRun();
        }
//        Car car= (Car) enhancer.create();
//        car.carRun();
    }


    static class Car{

        public void carRun(){
            System.out.println("汽车启动，开始形式.........");
        }


    }



    static class SafeCar extends Car{

        @Override
        public void carRun(){
            System.out.println("汽车启动，开始形式.......");
            super.carRun();
        }
    }



}
